有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java Android保留一个位图作为更改色调、对比度、饱和度等的源

我正在安卓应用程序中开发一个功能,用户可以使用SeekBar修改位图的饱和度、色调、对比度等。我为每个处理编写了不同的方法。这可以单独工作,但如果我更改位图的色调,并且在调用任何其他方法(例如饱和度)之前,我希望使用应用的色调进度等保留位图。如果进度设置为默认值,用户应该能够看到原始位图

比如说,, 如果我将位图的色调值更改为200。现在,如果我想编辑饱和度的新位图的饱和度应该与应用色调。如果我将饱和度和色调进度重置为默认值,那么用户应该能够看到原始位图颜色

我尝试了许多方法来实现这种行为,例如在每次方法调用之前复制像素,但都没有帮助。目前,对于每种位图处理类型,我只是在用户单击时将修改后的位图的像素复制到原始位图,但如果我重置所有值,则不会将位图更改为原始颜色。请看我的密码

我希望这将有助于理解这个问题

private Bitmap wallpaper, modifiedWallpaper;
private ImageView imageView;
private ImageButton contrast;
private ImageButton hue;
private ImageButton saturation;
private float contrastProgress;
private float hueProgress;
private float satProgress;
private boolean isBlur, isBright, isContrast;
private boolean isHue, isSaturation, isRGB;
private TextView currentMode;
private SeekBar seekBar;
private Paint paint;
private Canvas canvas;
private CardView editor;


@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    View view = inflater.inflate(R.layout.fragment_customize_wallpaper, container, false);
    imageView = view.findViewById(R.id.wallpaper);
    rgbContainer = view.findViewById(R.id.rgb);
    close = view.findViewById(R.id.close);
    currentMode = view.findViewById(R.id.current_mode);
    seekBar = view.findViewById(R.id.seekBar);
    seekBar.setOnSeekBarChangeListener(seekBarChangeListener);


    contrast = view.findViewById(R.id.contrast);
    hue = view.findViewById(R.id.hue);
    saturation = view.findViewById(R.id.saturation);

    contrast.setOnClickListener(this);
    hue.setOnClickListener(this);
    saturation.setOnClickListener(this);
    satProgress = 256f;

    loadWallpaper(final String wallpaperUrl);     
    return view;
}


private void loadWallpaper(final String wallpaperUrl) {
    Picasso.get().load(Constants.DOMAIN + wallpaperUrl).into(new Target() {
        @Override
        public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
            wallpaper = bitmap; //original loaded
            modifiedWallpaper = wallpaper.copy(Bitmap.Config.ARGB_8888, true);
            imageView.setImageBitmap(wallpaper);
        }

        @Override
        public void onBitmapFailed(Exception e, Drawable errorDrawable) {

        }

        @Override
        public void onPrepareLoad(Drawable placeHolderDrawable) {

        }
    });
}


@Override
public void onClick(View view) {
    switch (view.getId()) {
       case R.id.contrast : {
            wallpaper = modifiedWallpaper.copy(Bitmap.Config.ARGB_8888, true);
            isBlur = false;
            isBright = false;
            isContrast = true;
            isHue = false;
            isSaturation = false;
            isRGB = false;
            seekBar.setVisibility(View.VISIBLE);
            rgbContainer.setVisibility(View.GONE);
            changeIconTint();
            seekBar.setOnSeekBarChangeListener(null);
            seekBar.setMax(90);
            seekBar.setProgress((int) contrastProgress);
            seekBar.setOnSeekBarChangeListener(seekBarChangeListener);
            currentMode.setText("Contrast");
            break;
        }
        case R.id.hue : {
            wallpaper = modifiedWallpaper.copy(Bitmap.Config.ARGB_8888, true);
            isBlur = false;
            isBright = false;
            isContrast = false;
            isHue = true;
            isSaturation = false;
            isRGB = false;
            seekBar.setVisibility(View.VISIBLE);
            rgbContainer.setVisibility(View.GONE);
            changeIconTint();
            seekBar.setOnSeekBarChangeListener(null);
            seekBar.setMax(180);
            seekBar.setProgress((int) hueProgress);
            seekBar.setOnSeekBarChangeListener(seekBarChangeListener);
            currentMode.setText("Hue");
            break;
        }
        case R.id.saturation : {
            wallpaper = modifiedWallpaper.copy(Bitmap.Config.ARGB_8888, true);
            isBlur = false;
            isBright = false;
            isContrast = false;
            isHue = false;
            isSaturation = true;
            isRGB = false;
            seekBar.setVisibility(View.VISIBLE);
            rgbContainer.setVisibility(View.GONE);
            changeIconTint();
            seekBar.setOnSeekBarChangeListener(null);
            seekBar.setMax(512);
            seekBar.setProgress((int) satProgress);
            seekBar.setOnSeekBarChangeListener(seekBarChangeListener);
            currentMode.setText("Saturation");
            break;
        }
    }
}

private void changeContrast(float contrastProgress) {
    float cb = this.contrastProgress == 0 ? 0 : -(this.contrastProgress / 1.8f) * 5;
    ColorMatrix cm = new ColorMatrix(new float[]
            {
                    contrastProgress, 0, 0, 0, cb,
                    0, contrastProgress, 0, 0, cb,
                    0, 0, contrastProgress, 0, cb,
                    0, 0, 0, contrastProgress, 0
            });

    paint = new Paint();
    paint.setColorFilter(new ColorMatrixColorFilter(cm));
    modifiedWallpaper = wallpaper.copy(Bitmap.Config.ARGB_8888, true);
    canvas = new Canvas(modifiedWallpaper);
    canvas.drawBitmap(modifiedWallpaper, 0, 0, paint);
    imageView.setImageBitmap(modifiedWallpaper);
}

private void changeHue() {
    ColorMatrix cm = new ColorMatrix();
    float hueProgress = cleanValue() / 90f * (float) Math.PI;
    if (hueProgress == 0){
        return;
    }

    float cosVal = (float) Math.cos(hueProgress);
    float sinVal = (float) Math.sin(hueProgress);
    float lumR = 0.213f;
    float lumG = 0.715f;
    float lumB = 0.072f;
    float[] mat = new float[]
            {//logic };
    cm.postConcat(new ColorMatrix(mat));

    paint = new Paint();
    paint.setColorFilter(new ColorMatrixColorFilter(cm));
    modifiedWallpaper = wallpaper.copy(Bitmap.Config.ARGB_8888, true);
    canvas = new Canvas(modifiedWallpaper);
    canvas.drawBitmap(modifiedWallpaper, 0, 0, paint);
    imageView.setImageBitmap(modifiedWallpaper);
}

private void changeSaturation() {
    ColorMatrix colorMatrix = new ColorMatrix();
    colorMatrix.setSaturation(satProgress / 256);
    paint = new Paint();
    paint.setColorFilter(new ColorMatrixColorFilter(colorMatrix));
    modifiedWallpaper = wallpaper.copy(Bitmap.Config.ARGB_8888, true);
    canvas = new Canvas(modifiedWallpaper);
    canvas.drawBitmap(modifiedWallpaper, 0, 0, paint);
    imageView.setImageBitmap(modifiedWallpaper);
}

private SeekBar.OnSeekBarChangeListener seekBarChangeListener = new SeekBar.OnSeekBarChangeListener() 
{
    @Override
    public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
        if (isContrast) {
            contrastProgress = seekBar.getProgress();
            Log.d("Contrast", "" + (int) contrastProgress);
            changeContrast((float) (seekBar.getProgress() + 10) / 10);
            return;
        }
        if (isHue) {
            hueProgress = seekBar.getProgress();
            Log.d("Hue", "" + (int) hueProgress);
            changeHue();
            return;
        }
        if (isSaturation) {
            satProgress = seekBar.getProgress();
            Log.d("Saturation", "" + (int) satProgress);
            changeSaturation();
        }
    }

    @Override
    public void onStartTrackingTouch(SeekBar seekBar) {

    }

    @Override
    public void onStopTrackingTouch(SeekBar seekBar) {

    }
};

共 (1) 个答案

  1. # 1 楼答案

    应用筛选器时未保存状态。您可以创建一个newPaint,其中包含一个newColorMatrix和一个newBitmap。这就是为什么一个过滤器会覆盖上一个过滤器

    有几种方法可以解决这个问题。我认为最好的第一步是将“过滤”与“绘图”功能分开。示例:changeSaturation()在您的代码中,不仅会更改饱和度,还会将其绘制到屏幕上。 我是这样做的:

        @Override
        public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
            if (isContrast) contrast = (float) (seekBar.getProgress() + 10) / 10
            if (isHue) hue = seekBar.getProgress();
            if (isSaturation) saturation = seekBar.getProgress();
    
            ColorMatrix matrix = calculateColorMatrix(contrast, hue, saturation);
            drawBitmap(matrix);
        }
    
    
        private void drawBitmap(ColorMatrix colorMatrix) {
             Paint paint = new Paint();
             paint.setColorFilter(new ColorMatrixColorFilter(colorMatrix));
             modifiedWallpaper = wallpaper.copy(Bitmap.Config.ARGB_8888, true);
             canvas = new Canvas(modifiedWallpaper);
             canvas.drawBitmap(modifiedWallpaper, 0, 0, paint);
             imageView.setImageBitmap(modifiedWallpaper);
        }
    
        private ColorMatrix calculateColorMatrix(float contrast, hue, saturation) {
            ColorMatrix colorMatrix = new ColorMatrix();
    
            // saturation
            colorMatrix.setSaturation(satProgress / 256);
    
            // hue   
            float cosVal = (float) Math.cos(hueProgress);
            float sinVal = (float) Math.sin(hueProgress);
            float lumR = 0.213f;
            // logic...
            colorMatrix.postConcat(new ColorMatrix(mat));
    
            //contrast
            // logic...
            colorMatrix.postConcat(new ColorMatrix(new float[]
                {
                        contrastProgress, 0, 0, 0, cb,
                        0, contrastProgress, 0, 0, cb,
                        0, 0, contrastProgress, 0, cb,
                        0, 0, 0, contrastProgress, 0
                }));
    
            return colorMatrix;
        }
    

    这只是一种方法。可能是最简单的一个。如果不希望每次滑块移动时都创建所有过滤器,可以为每个过滤器保留三个不同的matrix一个,每次只修改其中一个

        ColorMatrix hue = new ColorMatrix();
        ColorMatrix sat = new ColorMatrix();
        ColorMatrix con = new ColorMatrix();
    
        @Override
        public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
            if (isContrast) {
             con = //logic to create contrast matrix
            }
            if (isHue) {
             hue //logic to create hue matrix
            }
            if (isSaturation) {
              //...
              sat.setSaturation(...)
            }
    
    
            ColorMatrix matrix = hue.postConcat(sat).postConcat(con);
            drawBitmap(matrix);
        }
    

    我还没有亲自测试过这段代码,您可能需要做一些更改,但我希望这会让您走上正确的方向